
/*
 * Copyright 2002-2021 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 *版权所有2002-2021原作者。
 *
 *根据Apache许可证2.0版许可（“许可证”）；
 *除非符合许可证的规定，否则您不得使用此文件。
 *您可以在以下网址获取许可证副本：
 *
 *https://www.apache.org/licenses/LICENSE-2.0
 *
 *除非适用法律要求或书面同意，软件
 *根据许可证进行的分发是在“按原样”的基础上进行的，
 *无任何明示或暗示的保证或条件。
 *有关管理权限的特定语言，请参阅许可证和
 *许可证下的限制。
 */

package org.springframework.scheduling.concurrent;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.lang.Nullable;

/**
 * Base class for setting up a {@link java.util.concurrent.ExecutorService}
 * (typically a {@link java.util.concurrent.ThreadPoolExecutor} or
 * {@link java.util.concurrent.ScheduledThreadPoolExecutor}).
 * Defines common configuration settings and common lifecycle handling.
 *
 * @author Juergen Hoeller
 * @since 3.0
 * @see java.util.concurrent.ExecutorService
 * @see java.util.concurrent.Executors
 * @see java.util.concurrent.ThreadPoolExecutor
 * @see java.util.concurrent.ScheduledThreadPoolExecutor
 */
/**
 *用于设置｛@link java.util.concurrent.ExecutorService｝的基类
 *（通常是｛@link java.util.concurrent.ThreadPoolExecutor｝或
 *｛@link java.util.concurrent.ScheduledThreadPoolExecutitor｝）。
 *定义通用配置设置和通用生命周期处理。
 *
 *@作者于尔根·霍勒
 *@自3.0起
 *@参见java.util.concurrent.ExecutorService
 *@参见java.util.concurrent.Executors
 *@请参阅java.util.concurrent.ThreadPoolExecutor
 *@请参阅java.util.concurrent.ScheduledThreadPoolExecutor
 */
@SuppressWarnings("serial")
public abstract class ExecutorConfigurationSupport extends CustomizableThreadFactory
		implements BeanNameAware, InitializingBean, DisposableBean {

	protected final Log logger = LogFactory.getLog(getClass());

	private ThreadFactory threadFactory = this;

	private boolean threadNamePrefixSet = false;

	private RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.AbortPolicy();

	private boolean waitForTasksToCompleteOnShutdown = false;

	private long awaitTerminationMillis = 0;

	@Nullable
	private String beanName;

	@Nullable
	private ExecutorService executor;


	/**
	 * Set the ThreadFactory to use for the ExecutorService's thread pool.
	 * Default is the underlying ExecutorService's default thread factory.
	 * <p>In a Jakarta EE or other managed environment with JSR-236 support,
	 * consider specifying a JNDI-located ManagedThreadFactory: by default,
	 * to be found at "java:comp/DefaultManagedThreadFactory".
	 * Use the "jee:jndi-lookup" namespace element in XML or the programmatic
	 * {@link org.springframework.jndi.JndiLocatorDelegate} for convenient lookup.
	 * Alternatively, consider using Spring's {@link DefaultManagedAwareThreadFactory}
	 * with its fallback to local threads in case of no managed thread factory found.
	 * @see java.util.concurrent.Executors#defaultThreadFactory()
	 * @see jakarta.enterprise.concurrent.ManagedThreadFactory
	 * @see DefaultManagedAwareThreadFactory
	 */
	/**
	 *将ThreadFactory设置为用于ExecutorService的线程池。
	 *Default是底层ExecutiorService的默认线程工厂。
	 *<p>在雅加达EE或其他支持JSR-236的托管环境中，
	 *考虑指定位于JNDI的ManagedThreadFactory：默认情况下，
	 *可在“java:comp/DefaultManagedThreadFactory”中找到。
	 *使用XML中的“jee:jndi查找”命名空间元素或编程
	 *｛@link org.springframework.jndi.JndiLocatorDelegate｝以方便查找。
	 *或者，考虑使用Spring的｛@link DefaultManagedAwareThreadFactory｝
	 *在找不到托管线程工厂的情况下，其回退到本地线程。
	 *@请参阅java.util.concurrent.Executors#defaultThreadFactory（）
	 *@参见jakarta.enterprise.courrent.ManagedThreadFactory
	 *@参见DefaultManagedAwareThreadFactory
	 */
	public void setThreadFactory(@Nullable ThreadFactory threadFactory) {
		this.threadFactory = (threadFactory != null ? threadFactory : this);
	}

	@Override
	public void setThreadNamePrefix(@Nullable String threadNamePrefix) {
		super.setThreadNamePrefix(threadNamePrefix);
		this.threadNamePrefixSet = true;
	}

	/**
	 * Set the RejectedExecutionHandler to use for the ExecutorService.
	 * Default is the ExecutorService's default abort policy.
	 * @see java.util.concurrent.ThreadPoolExecutor.AbortPolicy
	 */
	/**
	 *将RejectedExecutionHandler设置为用于ExecutiorService。
	 *Default是ExecutiorService的默认中止策略。
	 *@参见java.util.concurrent.ThreadPoolExecutior.AbortPolicy
	 */
	public void setRejectedExecutionHandler(@Nullable RejectedExecutionHandler rejectedExecutionHandler) {
		this.rejectedExecutionHandler =
				(rejectedExecutionHandler != null ? rejectedExecutionHandler : new ThreadPoolExecutor.AbortPolicy());
	}

	/**
	 * Set whether to wait for scheduled tasks to complete on shutdown,
	 * not interrupting running tasks and executing all tasks in the queue.
	 * <p>Default is "false", shutting down immediately through interrupting
	 * ongoing tasks and clearing the queue. Switch this flag to "true" if you
	 * prefer fully completed tasks at the expense of a longer shutdown phase.
	 * <p>Note that Spring's container shutdown continues while ongoing tasks
	 * are being completed. If you want this executor to block and wait for the
	 * termination of tasks before the rest of the container continues to shut
	 * down - e.g. in order to keep up other resources that your tasks may need -,
	 * set the {@link #setAwaitTerminationSeconds "awaitTerminationSeconds"}
	 * property instead of or in addition to this property.
	 * @see java.util.concurrent.ExecutorService#shutdown()
	 * @see java.util.concurrent.ExecutorService#shutdownNow()
	 */
	/**
	 *设置是否在关机时等待计划任务完成，
	 *不中断正在运行的任务并执行队列中的所有任务。
	 *<p>默认值为“false”，通过中断立即关闭
	 *正在进行的任务和清除队列。如果您
	 *更喜欢以更长的关闭阶段为代价完全完成任务。
	 *<p>请注意，Spring的容器在执行任务时会继续关闭
	 *正在完成。如果您希望此执行器阻止并等待
	 *在容器的其余部分继续关闭之前终止任务
	 *向下-例如，为了保持您的任务可能需要的其他资源-，
	 *设置｛@link#setAwaitTerminationSeconds“awaitTerminationSeconds”｝
	 *属性，而不是此属性或除此属性之外的属性。
	 *@请参阅java.util.concurrent.ExecutorService#shutdown（）
	 *@请参阅java.util.concurrent.ExecutorService#shutdownNow（）
	 */
	public void setWaitForTasksToCompleteOnShutdown(boolean waitForJobsToCompleteOnShutdown) {
		this.waitForTasksToCompleteOnShutdown = waitForJobsToCompleteOnShutdown;
	}

	/**
	 * Set the maximum number of seconds that this executor is supposed to block
	 * on shutdown in order to wait for remaining tasks to complete their execution
	 * before the rest of the container continues to shut down. This is particularly
	 * useful if your remaining tasks are likely to need access to other resources
	 * that are also managed by the container.
	 * <p>By default, this executor won't wait for the termination of tasks at all.
	 * It will either shut down immediately, interrupting ongoing tasks and clearing
	 * the remaining task queue - or, if the
	 * {@link #setWaitForTasksToCompleteOnShutdown "waitForTasksToCompleteOnShutdown"}
	 * flag has been set to {@code true}, it will continue to fully execute all
	 * ongoing tasks as well as all remaining tasks in the queue, in parallel to
	 * the rest of the container shutting down.
	 * <p>In either case, if you specify an await-termination period using this property,
	 * this executor will wait for the given time (max) for the termination of tasks.
	 * As a rule of thumb, specify a significantly higher timeout here if you set
	 * "waitForTasksToCompleteOnShutdown" to {@code true} at the same time,
	 * since all remaining tasks in the queue will still get executed - in contrast
	 * to the default shutdown behavior where it's just about waiting for currently
	 * executing tasks that aren't reacting to thread interruption.
	 * @see #setAwaitTerminationMillis
	 * @see java.util.concurrent.ExecutorService#shutdown()
	 * @see java.util.concurrent.ExecutorService#awaitTermination
	 */
	/**
	 *设置此执行器应该阻止的最大秒数
	 *以等待剩余任务完成执行
	 *在容器的其余部分继续关闭之前。尤其是
	 *如果您的剩余任务可能需要访问其他资源，则非常有用
	 *它们也由容器管理。
	 *<p>默认情况下，此执行器根本不会等待任务的终止。
	 *它将立即关闭，中断正在进行的任务并清除
	 *剩余的任务队列-或者，如果
	 *｛@link#setWaitForTasksToCompleteOnShutdown“waitForTasksDoCompleteOnshutdown”｝
	 *标志已设置为｛@code true｝，它将继续完全执行所有
	 *正在进行的任务以及队列中的所有剩余任务，与并行
	 *容器的其余部分正在关闭。
	 *<p>在任何一种情况下，如果使用此属性指定等待终止期，
	 *该执行器将等待给定的时间（max）来终止任务。
	 *根据经验，如果您设置
	 *“waitForTasksToCompleteOnShutdown”同时设置为｛@code true｝，
	 *因为队列中所有剩余的任务仍将被执行——相比之下
	 *到默认的关闭行为，只需等待当前
	 *执行对线程中断没有反应的任务。
	 *@参见#setAwaitTerminationMillis
	 *@请参阅java.util.concurrent.ExecutorService#shutdown（）
	 *@参见java.util.concurrent.ExecutorService#awaitTermination
	 */
	public void setAwaitTerminationSeconds(int awaitTerminationSeconds) {
		this.awaitTerminationMillis = awaitTerminationSeconds * 1000L;
	}

	/**
	 * Variant of {@link #setAwaitTerminationSeconds} with millisecond precision.
	 * @since 5.2.4
	 * @see #setAwaitTerminationSeconds
	 */
	/**
	 *｛@link#setAwaitTerminationSeconds｝的变量，精度为毫秒。
	 *@自5.2.4起
	 *@参见#setAwaitTerminationSeconds
	 */
	public void setAwaitTerminationMillis(long awaitTerminationMillis) {
		this.awaitTerminationMillis = awaitTerminationMillis;
	}

	@Override
	public void setBeanName(String name) {
		this.beanName = name;
	}


	/**
	 * Calls {@code initialize()} after the container applied all property values.
	 * @see #initialize()
	 */
	/**
	 *在容器应用所有属性值后调用｛@code initialize（）｝。
	 *@参见#initialize（）
	 */
	@Override
	public void afterPropertiesSet() {
		initialize();
	}

	/**
	 * Set up the ExecutorService.
	 */
	/**
	 *设置ExecutiorService。
	 */
	public void initialize() {
		if (logger.isDebugEnabled()) {
			logger.debug("Initializing ExecutorService" + (this.beanName != null ? " '" + this.beanName + "'" : ""));
		}
		if (!this.threadNamePrefixSet && this.beanName != null) {
			setThreadNamePrefix(this.beanName + "-");
		}
		this.executor = initializeExecutor(this.threadFactory, this.rejectedExecutionHandler);
	}

	/**
	 * Create the target {@link java.util.concurrent.ExecutorService} instance.
	 * Called by {@code afterPropertiesSet}.
	 * @param threadFactory the ThreadFactory to use
	 * @param rejectedExecutionHandler the RejectedExecutionHandler to use
	 * @return a new ExecutorService instance
	 * @see #afterPropertiesSet()
	 */
	/**
	 *创建目标｛@link java.util.concurrent.ExecutorService｝实例。
	 *由｛@code afterPropertiesSet｝调用。
	 *@param threadFactory要使用的threadFactory
	 *@param rejectedExecutionHandler要使用的RejectedExecution_Handler
	 *@返回一个新的ExecutorService实例
	 *@参见#afterPropertiesSet（）
	 */
	protected abstract ExecutorService initializeExecutor(
			ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler);


	/**
	 * Calls {@code shutdown} when the BeanFactory destroys
	 * the task executor instance.
	 * @see #shutdown()
	 */
	/**
	 *当BeanFactory销毁时调用｛@code shutdown｝
	 *任务执行器实例。
	 *@参见#shutdown（）
	 */
	@Override
	public void destroy() {
		shutdown();
	}

	/**
	 * Perform a shutdown on the underlying ExecutorService.
	 * @see java.util.concurrent.ExecutorService#shutdown()
	 * @see java.util.concurrent.ExecutorService#shutdownNow()
	 */
	/**
	 *对基础ExecutiorService执行关闭操作。
	 *@请参阅java.util.concurrent.ExecutorService#shutdown（）
	 *@请参阅java.util.concurrent.ExecutorService#shutdownNow（）
	 */
	public void shutdown() {
		if (logger.isDebugEnabled()) {
			logger.debug("Shutting down ExecutorService" + (this.beanName != null ? " '" + this.beanName + "'" : ""));
		}
		if (this.executor != null) {
			if (this.waitForTasksToCompleteOnShutdown) {
				this.executor.shutdown();
			}
			else {
				for (Runnable remainingTask : this.executor.shutdownNow()) {
					cancelRemainingTask(remainingTask);
				}
			}
			awaitTerminationIfNecessary(this.executor);
		}
	}

	/**
	 * Cancel the given remaining task which never commended execution,
	 * as returned from {@link ExecutorService#shutdownNow()}.
	 * @param task the task to cancel (typically a {@link RunnableFuture})
	 * @since 5.0.5
	 * @see #shutdown()
	 * @see RunnableFuture#cancel(boolean)
	 */
	/**
	 *取消从未建议执行的给定剩余任务，
	 *从｛@link ExecutitorService#shutdownNow（）｝返回。
	 *@param task要取消的任务（通常为｛@link RunnableFuture｝）
	 *@自5.0.5起
	 *@参见#shutdown（）
	 *@see RunnableFuture#cancel（布尔值）
	 */
	protected void cancelRemainingTask(Runnable task) {
		if (task instanceof Future) {
			((Future<?>) task).cancel(true);
		}
	}

	/**
	 * Wait for the executor to terminate, according to the value of the
	 * {@link #setAwaitTerminationSeconds "awaitTerminationSeconds"} property.
	 */
	/**
	 *根据
	 *｛@link#setAwaitTerminationSeconds“awaitTerminationSeconds”｝属性。
	 */
	private void awaitTerminationIfNecessary(ExecutorService executor) {
		if (this.awaitTerminationMillis > 0) {
			try {
				if (!executor.awaitTermination(this.awaitTerminationMillis, TimeUnit.MILLISECONDS)) {
					if (logger.isWarnEnabled()) {
						logger.warn("Timed out while waiting for executor" +
								(this.beanName != null ? " '" + this.beanName + "'" : "") + " to terminate");
					}
				}
			}
			catch (InterruptedException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Interrupted while waiting for executor" +
							(this.beanName != null ? " '" + this.beanName + "'" : "") + " to terminate");
				}
				Thread.currentThread().interrupt();
			}
		}
	}

}
